import sys, os
import serial
import serial.tools.list_ports
from PyQt5 import QtWidgets
from PyQt5.QtGui import QRegExpValidator, QIcon
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtCore import QTimer, QRegExp, QTime
from ui import Ui_Form



class Pyqt5_Serial(QtWidgets.QWidget, Ui_Form):
    def __init__(self):
        super(Pyqt5_Serial, self).__init__()
        self.setupUi(self)
        self.init()
        self.setWindowTitle("SerialTool")
        self.setWindowIcon(QIcon("D:\\test\\pyqt\\serialTool\\ico.png"))
        self.ser = serial.Serial()
        self.refresh_com()

        self.receive_num = 0
        self.send_num = 0
        self.receiveRecord.setText("接收：{0:>12}".format(self.receive_num))
        self.sendRecord.setText("发送：{0:>12}".format(self.send_num))

    def init(self):
        self.refreshCom.clicked.connect(self.refresh_com)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.data_receive)

        self.timer_send = QTimer()
        self.timer_send.timeout.connect(self.data_send)
        self.autoSend.stateChanged.connect(self.data_send_timer)

        self.timer_timestamp = QTimer()
        self.timer_timestamp.timeout.connect(self.update_time)
        self.timer_timestamp.start(1000)

        self.openCom.clicked.connect(self.open_close_com)
        self.send.clicked.connect(self.data_send)
        self.clearReceiveText.clicked.connect(self.clear_display)

        self.sendMs.setValidator(QRegExpValidator(QRegExp(r"[0-9]+")))
        self.sendMs.returnPressed.connect(self.data_send_timer)
        self.sendMs.setText('1000')

    def update_time(self):
        currenttime = QTime.currentTime()
        self.status.setText("当前时间：{}".format(currenttime.toString()))

    def data_send_timer(self):
        if self.autoSend.isChecked():
            self.timer_send.start(int(self.sendMs.text(), 10))
        else:
            self.timer_send.stop()
        self.sendMs.clearFocus()

    # 清除显示
    def clear_display(self):
        self.receiveText.setText("")

    # 刷新串口
    def refresh_com(self):
        plist = list(serial.tools.list_ports.comports())
        self.comList.clear()
        if len(plist) <= 0:
            print("No COM found")
        else:
            for com in plist:
                comName = com[0]
                self.comList.addItem(comName)

    # 打开/关闭串口
    def open_close_com(self):
        if self.ser.isOpen() == False:
            self.ser.port = self.comList.currentText()
            self.ser.baudrate = int(self.baudrate.currentText())
            self.ser.bytesize = int(self.databits.currentText())
            self.ser.stopbits = int(self.stopbits.currentText())
            dict = {'无':'N', '奇校验':'O', '偶校验':'E'}
            self.ser.parity   = dict[self.parity.currentText()]

            try:
                self.ser.open()
                self.openCom.setText("关闭串口")
                self.refreshCom.setEnabled(False)
                self.comList.setEnabled(False)
                self.baudrate.setEnabled(False)
                self.databits.setEnabled(False)
                self.stopbits.setEnabled(False)
                self.parity.setEnabled(False)
            except:
                QMessageBox.critical(self, "Port Error", "串口不存在或被占用")
                return None

            # 打开串口接收
            self.timer.start(2)

        else:
            try:
                self.ser.close()
                self.openCom.setText("打开串口")
                self.refreshCom.setEnabled(True)
                self.comList.setEnabled(True)
                self.baudrate.setEnabled(True)
                self.databits.setEnabled(True)
                self.stopbits.setEnabled(True)
                self.parity.setEnabled(True)
                self.timer.stop()
            except:
                QMessageBox.critical(self, "Port Error", "关闭串口失败")
                return None


    def data_receive(self):
        try:
            num = self.ser.inWaiting()
        except:
            num = 0
            print("串口异常")
        if num > 0:
            try:
                data = self.ser.read(num)
                num = len(data)
                #hex display
                if self.hexDisplay.isChecked():
                    out_s = ''
                    for i in range(0, len(data)):
                        out_s = out_s + '{:02X}'.format(data[i]) + ' '
                    self.receiveText.moveCursor(self.receiveText.textCursor().End)
                    self.receiveText.insertPlainText(out_s)
                else:
                    self.receiveText.moveCursor(self.receiveText.textCursor().End)
                    self.receiveText.insertPlainText(data.decode('GB2312','ignore'))
            except:
                print("串口异常")

            self.receive_num += num
            self.receiveRecord.setText("接收：{0:>12}".format(self.receive_num))


    def data_send(self):
        if self.ser.isOpen():
            input_s = self.sendText.toPlainText()
            if input_s != "":
                if self.hexSend.isChecked():
                    input_s = input_s.strip()
                    send_list = []
                    while input_s != '':
                        try:
                            num = int(input_s[0:2], 16)
                        except:
                            QMessageBox.critical(self, 'wrong data', '请输入16进制数据，以空格分开')
                            return None
                        input_s = input_s[2:].strip()
                        send_list.append(num)
                    input_s = bytes(send_list)
                else:
                    input_s = input_s.encode('GB2312')
                num = self.ser.write(input_s)
                self.send_num += num
                self.sendRecord.setText("发送：{0:>12}".format(self.send_num))





if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    serTool = Pyqt5_Serial()
    serTool.show()
    sys.exit(app.exec_())